home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / nslookup / send.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-27  |  5.8 KB  |  253 lines

  1. /*
  2.  * Copyright (c) 1985 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. static char sccsid[] = "@(#)send.c    5.9 (Berkeley) 6/18/88";
  20. #endif /* not lint */
  21.  
  22. /*
  23.  *******************************************************************************
  24.  *
  25.  *  send.c --
  26.  *
  27.  *    Routine to send request packets to a name server.
  28.  *
  29.  *    Modified version of 4.3BSD BIND  res_send.c 5.5 (Berkeley) 9/14/85
  30.  *
  31.  *******************************************************************************
  32.  */
  33.  
  34. #include <sys/types.h>
  35. #include <sys/time.h>
  36. #include <sys/socket.h>
  37. #include <netinet/in.h>
  38. #include <stdio.h>
  39. #include <arpa/nameser.h>
  40. #include <resolv.h>
  41. #include "res.h"
  42.  
  43. /*
  44.  *  Initialize the socket address info struct.
  45.  */
  46.  
  47. static struct sockaddr_in sin = { 
  48.     AF_INET,  
  49. };
  50.  
  51.  
  52. /*
  53.  *******************************************************************************
  54.  *
  55.  *   SendRequest --
  56.  *
  57.  *    Sends a request packet to a name server whose address
  58.  *    is specified by the first argument and returns with
  59.  *    the answer packet.
  60.  *
  61.  *  Results:
  62.  *    SUCCESS        - the request was sent and an answer 
  63.  *              was received.
  64.  *    TIME_OUT    - the virtual circuit connection timed-out 
  65.  *              or a reply to a datagram wasn't received.
  66.  *
  67.  *
  68.  *******************************************************************************
  69.  */
  70.  
  71. int
  72. SendRequest(nsAddrPtr, buf, buflen, answer, anslen, trueLenPtr)
  73.     struct in_addr     *nsAddrPtr;
  74.     char         *buf;
  75.     int         buflen;
  76.     char         *answer;
  77.     int         anslen;
  78.     int         *trueLenPtr;
  79. {
  80.     struct timeval     timeout;
  81.     register int     n;
  82.     u_short     packetId, len;
  83.     short         length;
  84.     char         *cp;
  85.     int         retry, v_circuit, resplen;
  86.     int         dsmask;
  87.  
  88.     int         numTimeOuts    = 0;
  89.     HEADER         *requestPtr    = (HEADER *) buf;
  90.     HEADER         *answerPtr    = (HEADER *) answer;
  91.  
  92.  
  93.     if (_res.options & RES_DEBUG2) {
  94.         printf("------------\nSendRequest(), len %d\n", buflen);
  95.         Print_query(buf, buf+buflen, 1);
  96.     }
  97.     sockFD = -1;
  98.  
  99.     /*
  100.      * See if a virtual circuit is required or desired.
  101.      */
  102.     v_circuit = (_res.options & RES_USEVC) || buflen > PACKETSZ;
  103.  
  104.     packetId = requestPtr->id;
  105.  
  106.     sin.sin_port    = htons(NAMESERVER_PORT);
  107.     sin.sin_addr    = *nsAddrPtr;
  108.  
  109.     /*
  110.      * Send request, RETRY times, or until successful
  111.      */
  112.     for (retry = _res.retry; --retry >= 0; ) {
  113.         if (v_circuit) {
  114.             /*
  115.              * Use virtual circuit.
  116.              */
  117.             if (sockFD < 0)
  118.                 sockFD = socket(AF_INET, SOCK_STREAM, 0);
  119.  
  120.             if (connect(sockFD, &sin, sizeof(sin)) < 0) {
  121.                 if (_res.options & RES_DEBUG) {
  122.                     perror("SendRequest");
  123.                 }
  124.                 (void) close(sockFD);
  125.                 sockFD = -1;
  126.                 continue;
  127.             }
  128.             /*
  129.              * Send length & message
  130.              */
  131.             len = htons(buflen);
  132.             if (write(sockFD, &len, sizeof(len)) != sizeof(len) ||
  133.                 write(sockFD, buf, buflen) != buflen) {
  134.                 if (_res.options & RES_DEBUG) {
  135.                     perror("SendRequest");
  136.                 }
  137.                 (void) close(sockFD);
  138.                 sockFD = -1;
  139.                 continue;
  140.             }
  141.             /*
  142.              * Receive length & response
  143.              */
  144.             cp = answer;
  145.             length = sizeof(short);
  146.             while(length > 0 && (n = read(sockFD, cp, length)) > 0){
  147.                 cp += n;
  148.                 length -= n;
  149.             }
  150.             if (n <= 0) {
  151.                 if (_res.options & RES_DEBUG) {
  152.                     perror("SendRequest");
  153.                 }
  154.                 (void) close(sockFD);
  155.                 sockFD = -1;
  156.                 continue;
  157.             }
  158.             cp = answer;
  159.             resplen = length = ntohs(*(short *)cp);
  160.             while(length > 0 && (n = read(sockFD, cp, length)) > 0){
  161.                 cp += n;
  162.                 length -= n;
  163.             }
  164.             if (n <= 0) {
  165.                 if (_res.options & RES_DEBUG) {
  166.                     perror("SendRequest");
  167.                 }
  168.                 (void) close(sockFD);
  169.                 sockFD = -1;
  170.                 continue;
  171.             }
  172.         } else {
  173.             /*
  174.              * Use datagrams.
  175.              */
  176.             if (sockFD < 0)
  177.                 sockFD = socket(AF_INET, SOCK_DGRAM, 0);
  178.  
  179.             if (sendto(sockFD, buf, buflen, 0, &sin,
  180.                  sizeof(sin)) != buflen) {
  181.                     perror("SendRequest: sendto");
  182.                     continue;
  183.             }
  184.             /*
  185.              * Wait for reply 
  186.              */
  187.             timeout.tv_sec = _res.retrans;
  188.             timeout.tv_usec = 0;
  189.             dsmask = 1 << sockFD;
  190.             n = select(sockFD+1, &dsmask, 0, 0, &timeout);
  191.             if (n < 0) {
  192.                 if (_res.options & RES_DEBUG) {
  193.                     perror("SendRequest: select");
  194.                 }
  195.                 continue;
  196.             }
  197.             if (n == 0) {
  198.                 /*
  199.                  * timeout
  200.                  */
  201.                 if (_res.options & RES_DEBUG) {
  202.                     printf("Timeout %d\n", ++numTimeOuts);
  203.                 }
  204.                 continue;
  205.             }
  206.              if ((resplen = recv(sockFD, answer, anslen, 0)) <= 0) {
  207.                 if (_res.options & RES_DEBUG) {
  208.                     perror("SendRequest: recv");
  209.                 }
  210.                 continue;
  211.             }
  212.             if (packetId != answerPtr->id) {
  213.                 /*
  214.                  * response from old query, ignore it
  215.                  */
  216.                 if (_res.options & RES_DEBUG2) {
  217.                     printf("------------\nOld answer:\n");
  218.                     Print_query(answer, answer+resplen, 1);
  219.                 }
  220.                 continue;
  221.             }
  222.             if (!(_res.options & RES_IGNTC) && answerPtr->tc) {
  223.                 /*
  224.                  * get rest of answer
  225.                  */
  226.                 if (_res.options & RES_DEBUG) {
  227.                     printf("truncated answer\n");
  228.                 }
  229.                 (void) close(sockFD);
  230.                 sockFD = -1;
  231.                 retry = _res.retry;
  232.                 v_circuit = 1;
  233.                 continue;
  234.             }
  235.         }
  236.         if (_res.options & RES_DEBUG) {
  237.             if (_res.options & RES_DEBUG2) 
  238.             printf("------------\nGot answer (%d bytes):\n",
  239.                 resplen);
  240.             else
  241.             printf("------------\nGot answer:\n");
  242.             Print_query(answer, answer+resplen, 1);
  243.         }
  244.         (void) close(sockFD);
  245.         sockFD = -1;
  246.         *trueLenPtr = resplen;
  247.         return (SUCCESS);
  248.     }
  249.     (void) close(sockFD);
  250.     sockFD = -1;
  251.     return (TIME_OUT);
  252. }
  253.